#ifndef MMD_IOT_SDK_H
#define MMD_IOT_SDK_H
#include <Arduino.h>
#include <ArduinoJson.h>
#include "Client.h"

typedef void (*poniter_fun)(JsonVariant ele); //定义一个函数指针

typedef struct poniter_desc
{
  char *key;
  poniter_fun fp;
} poniter_desc, *p_poniter_desc;

// 最多绑定20个回调
static poniter_desc poniter_array[20];
static p_poniter_desc p_poniter_array;

class MMDIoTSDK
{
private:
  // mqtt 链接信息，动态生成的
  static char mqttPwd[256];
  static char clientId[256];
  static char mqttUsername[100];
  static char domain[150];

  // 定时检查 mqtt 链接
  static void mqttCheckConnect();

  static void messageBufferCheck();
 

public:
  // 标记一些 topic 模板
  static char TOPIC_PROP_POST[150];
  static char TOPIC_PROP_SET[150];
  static char TOPIC_EVENT[150];
  // 在主程序 loop 中调用，检查连接和定时发送信息
  static void loop();

  /**
   * 初始化程序
   * @param espClient client
   * @param _mqttServer mqtt服务地址
   * @param _productKey 
   * @param _deviceName 
   * @param _deviceSecret
   */
  static void begin(Client &espClient,
                    const char *_mqttServer,
                    const char *_productKey,
                    const char *_deviceName,
                    const char *_deviceSecret);

  /**
   * 发送数据
   * @param param 字符串形式的json 数据，例如 {"${key}":"${value}"}
   */
  static void send(const char *param);

  /**
   * 发送Buffer数据
   */
  static void sendBuffer();

  /**
   * 添加Buffer float 格式数据
   * @param key 数据的 key
   * @param number 数据的值
   */
  static void addBuffer(char *key, float number);

  /**
   * 添加Buffer int 格式数据
   * @param key 数据的 key
   * @param number 数据的值
   */
  static void addBuffer(char *key, int number);

  /**
   * 添加Buffer double 格式数据
   * @param key 数据的 key
   * @param number 数据的值
   */
  static void addBuffer(char *key, double number);

  /**
   * 添加Buffer string 格式数据
   * @param key 数据的 key
   * @param text 数据的值
   */
  static void addBuffer(char *key, char *text);

  /**
   * 删除Buffer 数据
   * @param key 数据的 key
   */
  static void removeBuffer(char *key);

  /**
   * 卸载某个 key 的所有回调（慎用）
   * @param key 物模型的key
   */
  static int unbindData(char *key);

  /**
   * 绑定属性回调，云服务下发的数据包含此 key 会进入回调，用于监听特定数据的下发
   * @param key 物模型的key
   */
  static int bindData(char *key, poniter_fun fp);

  static boolean publish(const char *topic, const char *payload);

  /**
   * 订阅topic
   * @param topic 订阅的topic
   * @param qos 
   */
  static boolean subscribe(char *topic, uint8_t qos);

  /**
   * 订阅topic
   * @param topic 订阅的topic
   * @param fp 回调函数
   */
  static boolean subscribe(char *topic, poniter_fun fp);

  /**
   * 订阅topic
   * @param topic 订阅的topic
   * @param qos 
   * @param fp 回调函数
   */
  static boolean subscribe(char *topic, uint8_t qos, poniter_fun fp);

  /**
   * 取消订阅指定topic
   * @param topic 订阅的topic
   */
  static boolean unsubscribe(char *topic);
};
#endif
